import {loadInterfaceXML} from '../misc/fileUtils.js';
const SHOW_WEEKDATE_KEY = 'show-weekdate';
+const MAX_NOTIFICATION_BUTTONS = 3;
const NC_ = (context, str) => `${context}\u0004${str}`;
});
notification.connectObject(
'updated', this._onUpdated.bind(this),
+ 'action-added', (_, action) => this._addAction(action),
+ 'action-removed', (_, action) => this._removeAction(action),
+
'destroy', () => {
this.notification = null;
if (!this._closed)
this.close();
}, this);
+
+ this._actions = new Map();
+ this.notification.actions.forEach(action => {
+ this._addAction(action);
+ });
}
_getIcon() {
canClose() {
return true;
}
+
+ _addAction(action) {
+ if (!this._buttonBox) {
+ this._buttonBox = new St.BoxLayout({
+ x_expand: true,
+ style_class: 'notification-buttons-bin',
+ });
+ this.setActionArea(this._buttonBox);
+ global.focus_manager.add_group(this._buttonBox);
+ }
+
+ if (this._buttonBox.get_n_children() >= MAX_NOTIFICATION_BUTTONS)
+ return;
+
+ const button = new St.Button({
+ style_class: 'notification-button',
+ x_expand: true,
+ label: action.label,
+ });
+
+ button.connect('clicked', () => action.activate());
+
+ this._actions.set(action, button);
+ this._buttonBox.add_child(button);
+ }
+
+ _removeAction(action) {
+ this._actions.get(action)?.destroy();
+ this._actions.delete(action);
+ }
});
const NotificationSection = GObject.registerClass(
});
vbox.add_child(hbox);
- this._actionBin = new St.Widget({
+ this._actionBin = new St.Bin({
layout_manager: new ScaleLayout(),
visible: false,
});
}
setActionArea(actor) {
- if (actor == null) {
- if (this._actionBin.get_n_children() > 0)
- this._actionBin.get_child_at_index(0).destroy();
- return;
- }
-
- if (this._actionBin.get_n_children() > 0)
- throw new Error('Message already has an action area');
-
- this._actionBin.add_child(actor);
- this._actionBin.visible = this.expanded;
+ this._actionBin.child = actor;
+ this._actionBin.visible = actor && this.expanded;
}
addMediaControl(iconName, callback) {
expand(animate) {
this.expanded = true;
- this._actionBin.visible = this._actionBin.get_n_children() > 0;
+ this._actionBin.visible = !!this._actionBin.child;
const duration = animate ? MessageTray.ANIMATION_TIME : 0;
this._bodyStack.ease_property('@layout.expansion', 1, {
const MAX_NOTIFICATIONS_IN_QUEUE = 3;
const MAX_NOTIFICATIONS_PER_SOURCE = 3;
-const MAX_NOTIFICATION_BUTTONS = 3;
// We delay hiding of the tray if the mouse is within MOUSE_LEFT_ACTOR_THRESHOLD
// range from the point where it left the tray.
// @label: the label for the action's button
// @callback: the callback for the action
addAction(label, callback) {
- const action = new Action(label, callback);
+ const action = new Action(label, () => {
+ callback();
+
+ // We don't hide a resident notification when the user invokes one of its actions,
+ // because it is common for such notifications to update themselves with new
+ // information based on the action. We'd like to display the updated information
+ // in place, rather than pop-up a new notification.
+ if (this.resident)
+ return;
+
+ this.destroy();
+ });
this.actions.push(action);
this.emit('action-added', action);
}
activate() {
this.emit('activated');
- if (!this.resident)
- this.destroy();
+ // We don't hide a resident notification when the user invokes one of its actions,
+ // because it is common for such notifications to update themselves with new
+ // information based on the action. We'd like to display the updated information
+ // in place, rather than pop-up a new notification.
+ if (this.resident)
+ return;
+
+ this.destroy();
}
destroy(reason = NotificationDestroyedReason.DISMISSED) {
this.can_focus = false;
this.add_style_class_name('notification-banner');
- this._buttonBox = null;
-
- this._addActions();
-
this.notification.connectObject('activated', () => {
// We hide all types of notifications once the user clicks on
// them because the common outcome of clicking should be the
this.emit('done-displaying');
}, this);
}
-
- _onUpdated(n, clear) {
- super._onUpdated(n, clear);
-
- if (clear) {
- this.setActionArea(null);
- this._buttonBox = null;
- }
-
- this._addActions();
- }
-
- _addActions() {
- this.notification.actions.forEach(action => {
- this.addAction(action.label, () => action.activate());
- });
- }
-
- addButton(button, callback) {
- if (!this._buttonBox) {
- this._buttonBox = new St.BoxLayout({
- style_class: 'notification-actions',
- x_expand: true,
- });
- this.setActionArea(this._buttonBox);
- global.focus_manager.add_group(this._buttonBox);
- }
-
- if (this._buttonBox.get_n_children() >= MAX_NOTIFICATION_BUTTONS)
- return null;
-
- this._buttonBox.add_child(button);
- button.connect('clicked', () => {
- callback();
-
- if (!this.notification.resident) {
- // We don't hide a resident notification when the user invokes one of its actions,
- // because it is common for such notifications to update themselves with new
- // information based on the action. We'd like to display the updated information
- // in place, rather than pop-up a new notification.
- this.emit('done-displaying');
- this.notification.destroy();
- }
- });
-
- return button;
- }
-
- addAction(label, callback) {
- const button = new St.Button({
- style_class: 'notification-button',
- label,
- x_expand: true,
- can_focus: true,
- });
-
- return this.addButton(button, callback);
- }
});
export const Source = GObject.registerClass({